/******************************************************************************
 * Author:      671643387
 * Created:     2016/9/28
 *****************************************************************************/

var clone = require('clone');
var mUtil = require('./util.js');
var mjMark = require('./mjmark.js');

/**
 * 检查玩家能否胡牌
 * @param player    玩家数据
 * @param card      牌
 * @param me        牌是否是玩家摸的
 */
function checkHupai(player, card, me) {
    // 检查玩家手牌能否胡牌
    var handCards = clone(player.getHandCards());
    handCards.add(card);

    // 检查是不是7对
    var is7Dui = check7Dui(handCards);
    if (is7Dui) {
        // 检查是不是清一色
        if (checkQingYiSe(handCards)) {
            // 清七对
            player.pushHuPaiType(mjMark.HUCARD_TYPE_QINGQIDUI);
        } else {
            // 七对
            player.pushHuPaiType(mjMark.HUCARD_TYPE_QIDUI);
        }

        return true;
    }

    // 检查是不是龙7对
    var isLoing7Dui = checkLong7Dui(player.getHandCards(), card);
    if (isLoing7Dui) {
        if (checkQingYiSe(handCards)) {
            // 清龙背
            player.pushHuPaiType(mjMark.HUCARD_TYPE_QINGLONGBEI);
        } else {
            // 龙7对
            player.pushHuPaiType(mjMark.HUCARD_TYPE_LONGQIDUI);
        }
        return;
    }

    // 检查是不是清一色
    var isQingYiSe = checkQingYiSe(handCards, player.getGangs(), player.getPengs());

    // 通用检查
    var huiPaiArr = checkCanHupai(handCards);
    if (huiPaiArr.length > 0) {
        // 检查胡牌模型里面有没有大对子
        if (checkHasDaDuiZi(huiPaiArr)) {
            if (isQingYiSe) {
                // 清大对
                player.pushHuPaiType(mjMark.HUCARD_TYPE_QINGDADUI);
            } else {
                // 大对子
                player.pushHuPaiType(mjMark.HUCARD_TYPE_DADUI);
            }

            // 检查是否单调
            if (player.getHandCards().getRemainCardNum() == 1) {
                player.pushHuPaiType(mjMark.HUCARD_TYPE_DANDIAO);
            }

        } else {
            if (isQingYiSe) {
                // 清一色
                player.pushHuPaiType(mjMark.HUCARD_TYPE_QINGYISE);
            } else {
                // 平糊
                player.pushHuPaiType(mjMark.HUCARD_TYPE_PING);
            }
        }

        return true;
    }
    return false;
}

function checkHasDaDuiZi(huiPaiArr) {
    for (var key in huiPaiArr) {
        if (!huiPaiArr.hasOwnProperty(key)) {
            continue;
        }

        // 玩家手中就一张牌
        var huiPaiMod = huiPaiArr[key];
        if (huiPaiMod.sequences.length == 0) {
            return true;
        }

        // 检查3张牌是不是都是一样的牌
        var allSameThree = true;
        for (var sKey in huiPaiMod.sequences) {
            if (!huiPaiMod.sequences.hasOwnProperty(sKey)) {
                continue;
            }

            var sseq = huiPaiMod.sequences[sKey];
            if (sseq[0] != sseq[1]) {
                allSameThree = false;
                break;
            }
        }
        if (allSameThree) {
            return true;
        }
    }

    return false;
}

function HupaiSt() {
    this.pair = 0;
    this.sequences = [];
}

function checkCanHupai(handCards) {
    // 检查 3n + 2
    if ((handCards.num - 2) % 3 != 0) {
        return false;
    }

    var hpArr = [];

    var cards = handCards.cards;
    for (var iCard = 0; iCard < cards.length; ++iCard) {
        if (cards[iCard].num == 0) {
            continue;
        }

        if (cards[iCard].num >= 2) {

            var hpSt = new HupaiSt();
            hpSt.pair = cards[iCard].value; // 将牌

            var newHandCards = clone(handCards);

            // 扣除2张将牌
            newHandCards.decCard(cards[iCard], 2);
            checkout3(newHandCards, hpSt, hpArr);
        }
    }

    return hpArr;
}

function checkout3(handCards, hpSt, hpArr) {
    if (handCards.num == 0) {
        hpArr.push(hpSt);
        return;
    }

    var cards = handCards.cards;
    for (var iCard = 0; iCard < cards.length; ++iCard) {
        if (cards[iCard].num == 0) {
            continue;
        }

        var card = cards[iCard];
        if (card.num <= 2 || card.num == 4) {
            var card2 = cards[iCard + 1];
            var card3 = cards[iCard + 2];

            if (!card2 || !card3) {
                return;
            }
            if (card2.num == 0 || card3.num == 0) {
                return;
            }
            var type = Math.floor((card.value - 1) / 9);
            var type2 = Math.floor((card2.value - 1) / 9);
            var type3 = Math.floor((card3.value - 1) / 9);
            if (!(type == type2 && type == type3)) {
                return;
            }

            hpSt.sequences.push([card.value, card2.value, card3.value]);

            handCards.decCard(card, 1);
            handCards.decCard(card2, 1);
            handCards.decCard(card3, 1);
            checkout3(handCards, hpSt, hpArr);
            break;
        } else if (card.num == 3) {
            // 检查能否和后面构成顺子
            var card2 = cards[iCard + 1];
            var card3 = cards[iCard + 2];

            if ((card2 && card3) && (card2.num == 3 && card3.num == 3)) {
                // 作为顺子
                var newHandCards = clone(handCards);
                var newHpSt = clone(hpSt);

                newHpSt.sequences.push([card.value, card2.value, card3.value]);

                newHandCards.decCard(card, 1);
                newHandCards.decCard(card2, 1);
                newHandCards.decCard(card3, 1);
                checkout3(newHandCards, newHpSt, hpArr);
            }

            // 作为暗刻
            hpSt.sequences.push([card.value, card.value, card.value]);
            handCards.decCard(card, 3);
            checkout3(handCards, hpSt, hpArr);
            break;
        }
    }
}

/**
 * 检查玩家的牌是不是7对
 * @param handCards
 */
function check7Dui(handCards) {
    var numDuiZi = 0;
    var cards = handCards.cards;

    for (var iCard = 0; iCard < cards.length; ++iCard) {
        if (cards[iCard].num == 0) {
            continue;
        }

        if (cards[iCard].num == 2) {
            numDuiZi += 1;
        } else if (cards[iCard].num == 4) {
            numDuiZi += 2;
        }
    }

    return (numDuiZi == 7);
}

/**
 * 检查是不是清一色
 * @param handCards
 */
function checkQingYiSe(handCards, gangs, pengs) {
    var minValue = 0;
    var maxValue = 0;

    var cards = handCards.cards;
    minValue = cards[cards.length - 1].value;

    for (var iCard = 0; iCard < cards.length; ++iCard) {
        if (cards[iCard].num == 0) {
            continue;
        }

        maxValue = Math.max(cards[iCard].value, maxValue);
        minValue = Math.min(cards[iCard].value, minValue);
    }

    if (gangs) {
        gangs.forEach(function(gang){
            var val = gang[0];
            maxValue = Math.max(val, maxValue);
            minValue = Math.min(val, minValue);
        });
    }

    if (pengs) {
        pengs.forEach(function(peng){
            var val = peng[0];
            maxValue = Math.max(val, maxValue);
            minValue = Math.min(val, minValue);
        });
    }

    if ((inRange(minValue, 1, 9) && inRange(maxValue, 1, 9))
        || inRange(minValue, 10, 18) && inRange(maxValue, 10, 18)
        || inRange(minValue, 19, 27) && inRange(maxValue, 19, 27)) {
        return true;
    }
    return false;
}

/**
 * 检查是不是龙七对
 * @param handCards 玩家手牌
 * @param card      要胡的牌
 */
function checkLong7Dui(handCards, card) {
    // 检查玩家手牌是不是5个对子和三张相同的牌
    var numDuiZi = 0;
    var treeCardVal = 0;

    handCards.cards.forEach(function(eCard){
        if (eCard.num == 3) {
            treeCardVal = eCard.value;
        } else if (eCard.num == 2) {
            numDuiZi += 1;
        } else if (eCard.num == 4) {
            numDuiZi += 2;
        }
    });

    if (numDuiZi == 5 && treeCardVal != 0) {
        return (card.value == treeCardVal);
    }
    return false;
}

function inRange(value, min, max) {
    return value >= min && value <= max;
}

/**
 * 检查玩家是否听牌
 * @param player    玩家数据
 */
function checkHearPai(player) {
    var isTingPai = false;

    // 检查玩家手牌能否听牌
    for(var key = 1; key <= 27; ++key) {
        var card = {value: +key};
        if (checkHupai(player, card, false)) {
            isTingPai = true;
        }
    }
    return isTingPai;
}
exports.checkHearPai = checkHearPai;
exports.checkHupai = checkHupai;


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 测试胡牌算法使用

var MAX_CARDS = 27;

function HandCards() {
    this.num = 0;           // 当前牌总数
    this.cards = [];        // 玩家手牌

    this.init();
}
HandCards.prototype = {
    // 初始化
    init: function() {
        for (var iCard = 0; iCard < MAX_CARDS; ++iCard) {
            this.cards[iCard] = {
                value : iCard + 1,
                num : 0,
            };
        }
    },

    // 添加手牌
    adds: function(cards) {
        var _me = this;
        cards.forEach(function(card){
            var value = (card.type - 1) * 9 + card.value;
            var newCard = _me.cards[value - 1];
            newCard.num += 1;
            _me.cards[value - 1] = newCard;
            _me.num += 1;
        });
    },

    // 增加一张手牌
    add: function(card) {
        var myCard = this.cards[card.value - 1];
        myCard.num += 1;
        this.num += 1;
    },

    // 获取手牌有几个和这张牌一样的牌
    hasSame: function(card) {
        var myCard = this.cards[card.value - 1];
        return myCard.num;
    },

    // 减少手牌
    decCard: function(card, num) {
        var myCard = this.cards[card.value - 1];
        myCard.num -= num;
        this.num -= num;
    },

    // 获取手牌同步数据
    getSyncData: function() {
        return this.cards;
    },

    // 获取还剩余几张手牌
    getRemainCardNum: function() {
        return this.num;
    }
};

var handCards = new HandCards();
handCards.num = 11;
handCards.cards = [
    {
        "value": 1,
        "num": 0
    },
    {
        "value": 2,
        "num": 0
    },
    {
        "value": 3,
        "num": 0
    },
    {
        "value": 4,
        "num": 0
    },
    {
        "value": 5,
        "num": 0
    },
    {
        "value": 6,
        "num": 1
    },
    {
        "value": 7,
        "num": 1
    },
    {
        "value": 8,
        "num": 1
    },
    {
        "value": 9,
        "num": 0
    },
    {
        "value": 10,
        "num": 0
    },
    {
        "value": 11,
        "num": 0
    },
    {
        "value": 12,
        "num": 0
    },
    {
        "value": 13,
        "num": 0
    },
    {
        "value": 14,
        "num": 2
    },
    {
        "value": 15,
        "num": 0
    },
    {
        "value": 16,
        "num": 1
    },
    {
        "value": 17,
        "num": 1
    },
    {
        "value": 18,
        "num": 1
    },
    {
        "value": 19,
        "num": 0
    },
    {
        "value": 20,
        "num": 0
    },
    {
        "value": 21,
        "num": 3
    },
    {
        "value": 22,
        "num": 0
    },
    {
        "value": 23,
        "num": 0
    },
    {
        "value": 24,
        "num": 0
    },
    {
        "value": 25,
        "num": 0
    },
    {
        "value": 26,
        "num": 0
    },
    {
        "value": 27,
        "num": 0
    }
];

//var arr = checkCanHupai(handCards);
//console.log(arr);